function parseIntEx(n) {
	if (Math.abs(n) < 1) { return 0; }
	return parseInt(n);
}

Number.prototype.toFixedEx = function(n) {
	n = n || 0;
	if (n <= 0) {
		return parseInt(this);
	}
	
	var _str = this + '';

	var this_big = new BigNumber(_str);
	var base   = Math.pow(10, n);
	var _int   = Math.abs(parseIntEx(this));
	var _total = Math.abs(parseIntEx(this_big.times(base)));
	var _float = _total % base;
	
	var float_str = _float + '';
	if (float_str.length < n) {
		var zero_str = new Array(n - float_str.length + 1).join('0');
		if (_float < Math.pow(10, n-1)) {
			float_str = zero_str +  float_str;
		} else {
			float_str += zero_str;
		}
	}
	return (this >= 0 ? '' : '-') + _int + '.' + float_str;
}

String.prototype.toFixedEx = function(n) {
	var x = new BigNumber(this).toFixed(15);
	var str = x.split('.');
	return str[0] + '.' + str[1].substr(0, n);
}

Number.prototype.toZeroFillIntStr = function(n) {
	n = n || 0;
	var s = parseIntEx(this) + '';
	if (s.length < n) {
		return new Array(n - s.length + 1).join('0') + s;
	}
	return s;
}


//
// ("1231231234.1234").formatEx() -> "1,231,231,234.1234"
// ("123123123").formatEx()       ->  "123,123,123"
//
String.prototype.formatSeparator = function() {
	var re = /(-?\d+)(\d{3})/;
	var p_idx    = this.lastIndexOf(".");
	var tail_str = (p_idx == -1 ? null : this.substring(p_idx + 1));
	var int_str  = (p_idx == -1 ? this : this.substring(0, p_idx));
	while (re.test(int_str)) {
		int_str = int_str.replace(re, "$1,$2");
	}
	return int_str + (tail_str ? "." + tail_str : '');
}
Number.prototype.formatSeparator = function() {
	var num = this + '';
	return num.formatSeparator();
}

// formatEx(n)
//   n -> toFixed(n)
Number.prototype.formatEx = function(n) {
	n = n || 0;
	return this.toFixedEx(n).formatSeparator();
}
String.prototype.formatEx = function(n) {
	n = n || 0;
	var num = this * 1.0;
	return num.formatEx(n);
}


//Number.prototype.formatExWithSmall = function(n) {
//    n = n || 0;
//
//    var _int = parseIntEx(this);
//    if (n == 0) {
//    	return _int.formatSeparator();
//    }
//    var _float = (this - _int).toFixedEx(n);
//    var _float_str = '<small>' + _float.substr(1) + '</small>';
//    return _int.formatSeparator() + _float_str;
//}

Number.prototype.formatExWithSmall = function(n) {
	n = n || 0;
	
	var _int = parseIntEx(this);
	if (n == 0) {
		return _int.formatSeparator();
	}
	
	var _float = this.toFixedEx(n).split('.').pop();
	
	var _float_str = '<small>.' + _float + '</small>';
	return _int.formatSeparator() + _float_str;
}

String.prototype.formatExWithSmall = function(n) {
	n = n || 0;
	var num = this * 1.0;
	return num.formatExWithSmall(n);
}


var config = {
	websocket: {
			host: 'letsdice.com',
			port: 443,
		},
	bet: {
		'min_win_odds': .0001,
		'max_win_odds': 97,
		'min_bet_amount': 0.00000001,
		'house_edge': 0.0198,
		'max_payout': 980200,
		'min_payout': 1.01051546,
	},
	jackpot: {
		percent: 0.0048, 
		min_value: 100000000, // sotoshi
	},
	bankroll: {
		max_win_percent: 0.02,
	}
};

var randomEx;
randomEx = function() {
  var array, error;
  try {
    array = new Uint16Array(1);
    window.crypto.getRandomValues(array);
    return array[0] / 65535;
  } catch (_error) {
    error = _error;
    return Math.random();
  }
};
var util = {
	'random_str': function(length) {
	    var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'.split('');
	    length = length || 32;
	    var str = '';
	    for (var i = 0; i < length; i++) {
	        str += chars[Math.floor(randomEx() * chars.length)];
	    }
	    return str;
	},
	'multiper': function(change_to_win) {
		var payout = new BigNumber(1).minus(config.bet.house_edge).dividedBy(change_to_win).times(100);
		return payout.toString().toFixedEx(8);
	},
	'win_odds': function(multiper) {
		var win_odds = new BigNumber(1).minus(config.bet.house_edge).times(100).dividedBy(multiper);
        return win_odds.toString().toFixedEx(4);
	},
	'win_odds_min': function(bet_amount, max_profit) {
		var max_profit = new BigNumber(max_profit);
		var bet_amount = new BigNumber(bet_amount);
		var multiper = max_profit.dividedBy(bet_amount).plus(1);
		if (multiper.cmp(config.bet.max_payout) == 1) {
			multiper = new BigNumber(config.bet.max_payout);
		}
		var win_odds = new BigNumber(util.win_odds(multiper));
		
		while (1) {
			multiper = new BigNumber(util.multiper(win_odds.toString().toFixedEx(4)));
			if (multiper.minus(1).times(bet_amount).cmp(max_profit) == -1 &&
				win_odds.minus('0.0001').cmp(config.bet.min_win_odds) == 1) {
				win_odds = win_odds.minus('0.0001');
				continue;
			}
			break;
		}
		multiper = new BigNumber(util.multiper(win_odds.toString().toFixedEx(4)));
		if (multiper.minus(1).times(bet_amount).cmp(max_profit) == 1) {
			win_odds = win_odds.plus('0.0001');
		}

        return win_odds.toString().toFixedEx(4);
	},
	'win_odds_max': function(bet_amount) {
		// 1 satoshi = (mul-1) * bet
		var bet_amount = new BigNumber(bet_amount);
		var multiper = g_coin_obj.dividedBy(bet_amount).plus(1).toString().toFixedEx(8);
		var win_odds = new BigNumber(util.win_odds(multiper));
		
		while (1) {
			multiper = new BigNumber(util.multiper(win_odds.toString().toFixedEx(4)));
			if (multiper.minus(1).times(bet_amount).cmp(g_coin_obj) == 1 &&
					win_odds.plus('0.0001').cmp(config.bet.max_win_odds) == -1) {
				win_odds = win_odds.plus('0.0001');
				continue;
			}
			break;
		}
		multiper = new BigNumber(util.multiper(win_odds.toString().toFixedEx(4)));
		if (multiper.minus(1).times(bet_amount).cmp(g_coin_obj) == -1) {
			win_odds = win_odds.minus('0.0001');
		}
		
        return win_odds.toString().toFixedEx(4);
	},
	'bet_amount_max': function(win_odds, max_profit) {
		var max_profit = new BigNumber(max_profit);
		var multiper   = new BigNumber(util.multiper(win_odds));
		
		var bet_amount = max_profit.dividedBy(multiper.minus(1)).toString().toFixedEx(8);
		bet_amount = new BigNumber(bet_amount);
		
		while (bet_amount.times(multiper.minus(1)).cmp(max_profit) == -1) {
			bet_amount = bet_amount.plus(g_coin_obj);
		}
		while (bet_amount.times(multiper.minus(1)).cmp(max_profit) == 1) {
			bet_amount = bet_amount.minus(g_coin_obj);
		}
		
		return bet_amount.toString().toFixedEx(8);
	},
	'bet_amount_min': function(win_odds) {
		// 1 satoshi = (mul-1) * bet
		var multiper = new BigNumber(util.multiper(win_odds));
		var bet_amount = g_coin_obj.dividedBy(multiper.minus(1)).toString().toFixedEx(8);
		bet_amount = new BigNumber(bet_amount);
		
		while (bet_amount.times(multiper.minus(1)).cmp(g_coin_obj) == 1) {
			bet_amount = bet_amount.minus(g_coin_obj);
		}
		while (bet_amount.times(multiper.minus(1)).cmp(g_coin_obj) == -1) {
			bet_amount = bet_amount.plus(g_coin_obj);
		}
		return bet_amount.toString().toFixedEx(8);
	}
};


